﻿using Camelot.JSONAPI.Business;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.WindowsTokenService;
using Microsoft.SharePoint;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using Command = Camelot.JSONAPI.Models.Command;

namespace Camelot.JSONAPI
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true)]
    public class JsonService : IJsonService
    {

        public JsonService()
        {
            //Thread.CurrentPrincipal = HttpContext.Current.User;
        }

        public string Items(string command)
        {
            // Test if array or not
            var isCommandArray = Regex.IsMatch(command.Trim(), @"^\[.*?\]$");
            string jsonReturn = string.Empty;

            ClaimsIdentity claimsIdentity = (Microsoft.IdentityModel.Claims.ClaimsIdentity)Thread.CurrentPrincipal.Identity;
            string upn = claimsIdentity.Claims.First(c => c.ClaimType == ClaimTypes.Upn).Value;
            WindowsIdentity windowsIdentity = S4UClient.UpnLogon(upn);
            using (windowsIdentity.Impersonate())
            {
                if (isCommandArray)
                {
                    List<Command> commandObj = JsonConvert.DeserializeObject<List<Command>>(command);

                    List<string> ret = commandObj.Select(ExecuteFactory.Execute).ToList();
                    jsonReturn = string.Format("[{0}]", string.Join(",", ret.ToArray()));
                }
                else
                {
                    Command commandObj = JsonConvert.DeserializeObject<Command>(command);
                    jsonReturn = ExecuteFactory.Execute(commandObj);
                }
            }

            return jsonReturn;
        }


        [OperationBehavior(Impersonation = ImpersonationOption.Allowed)]
        public string GetUser()
        {
            //var b = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity;
            //var cc = OperationContext.Current.ServiceSecurityContext.WindowsIdentity;

            try
            {
                //var userName = claimsIdentity.Claims.First(x => x.ClaimType.Equals("http://schemas.microsoft.com/sharepoint/2009/08/claims/userlogonname")).Value;
                //var userEmail = claimsIdentity.Claims.First(x => x.ClaimType.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn")).Value;

                ClaimsIdentity claimsIdentity = (Microsoft.IdentityModel.Claims.ClaimsIdentity)Thread.CurrentPrincipal.Identity;
                string upn = claimsIdentity.Claims.First(c => c.ClaimType == ClaimTypes.Upn).Value;
                WindowsIdentity windowsIdentity = S4UClient.UpnLogon(upn);
                using (windowsIdentity.Impersonate())
                {
                    return WindowsIdentity.GetCurrent().Name;
                }
            }
            catch
            { }

            WindowsImpersonationContext context = null;
            ServiceSecurityContext securityContext = OperationContext.Current.ServiceSecurityContext;

            try
            {
                if (securityContext != null &&
                    (securityContext.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation
                    || securityContext.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Delegation))
                {
                    context = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Impersonate();
                }

                return WindowsIdentity.GetCurrent().Name;
            }
            catch (Exception ex)
            {
                return WindowsIdentity.GetCurrent().Name;
            }
            finally
            {
                if (context != null)
                    context.Dispose();
            }
        }

    }
}
